#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import ast
import json
import socket
import time
import traceback


class JakaZuRobot:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    value_dict = {}
    """value_dict = {"joint_actual_position": "", "actual_position": "", "din": "", "dout": "", "ain": "", "aout": "",
                  "tio_din": "", "tio_dout": "",
                  "tio_ain": "", "task_state": "", "homed": "", "task_mode": "", "interp_state": "", "enabled": "",
                  "paused": "", "rapidrate": "",
                  "current_tool_id": "", "current_user_id":"", "protective_stop": "", "on_soft_limit": "", "emergency_stop": "",
                  "drag_near_limit": "", "funcdi": "",
                  "user_defined_variable": "", "drag_status": ""}"""
    # keyCode = ["actual_position", "dout"]
    """keyCode = ["joint_actual_position", "actual_position", "din", "dout", "ain", "aout", "tio_din", "tio_dout",
               "tio_ain", "task_state", "homed", "task_mode", "interp_state", "enabled", "paused", "rapidrate",
               "current_tool_id", "current_user_id", "protective_stop", "on_soft_limit", "emergency_stop", "drag_near_limit", "funcdi",
               "user_defined_variable", "drag_status"]"""

    def __init__(self):
        pass

    def connect_socket(self, ip, port, retry=3):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        while retry > 0:
            try:
                self.sock.connect((ip, port))
                # print('connect success.')
                return True
            except Exception:
                print(traceback.format_exc())
                time.sleep(1)
                retry = retry - 1
        return False

    def close_socket(self):
        self.sock.close()

    def get_all_data(self):
        data_recv = self.sock.recv(4096).decode()
        # print("recv:\n", data_recv)
        if data_recv.startswith("{") and data_recv.endswith("}"):
            try:
                self.value_dict = json.loads(data_recv)
                del data_recv
                return self.value_dict
            except Exception:
                del data_recv
                return self.value_dict
                # print(traceback.format_exc())
        else:
            del data_recv
            return self.value_dict

    """def split_data(self, data):
        line_list = data.splitlines(False)
        for line in line_list:
            if line.endswith(')'):
                item_list = line.split(':', 1)
                if self.value_dict.has_key(item_list[0]):
                    if item_list[0] == 'user_defined_variable':
                        # print("user_defined_variable:"+item_list[1])
                        js = item_list[1].replace('(', '').replace(')', '').replace('\'', '\"')
                        # print("user_defined_variable json:" + js)
                        try:
                            value_list = json.loads(js)
                        except Exception:
                            # print(traceback.format_exc())
                            continue
                    else:
                        if item_list[1].find(','):
                            try:
                                value_list = ast.literal_eval(item_list[1])
                            except Exception:
                                # print(traceback.format_exc())
                                continue
                        else:
                            value_list = item_list[1]
                    self.value_dict[item_list[0]] = value_list

            # --------------------------------------------- #
            if line.startswith(key) and line.endswith(')'):
                item_list = line.split(':', 1)
                if item_list[0] == 'user_defined_variable':
                    # print("user_defined_variable:"+item_list[1])
                    js = item_list[1].replace('(', '').replace(')', '').replace('\'', '\"')
                    # print("user_defined_variable json:" + js)
                    try:
                        value_list = json.loads(js)
                    except Exception:
                        # print(traceback.format_exc())
                        continue
                else:
                    if item_list[1].find(','):
                        try:
                            value_list = ast.literal_eval(item_list[1])
                        except Exception:
                            # print(traceback.format_exc())
                            continue
                    else:
                        value_list = item_list[1]
                self.value_dict[item_list[0]] = value_list
        # for item in value_dict.items():
        #     print(item)
        # return self.value_dict"""

    def send_get_data(self, sendDict):
        self.sock.sendall(sendDict.encode())
        data_send = self.sock.recv(4096).decode()
        # print("data_send in client:", data_send)
        try:
            self.value_dict = json.loads(data_send)
            del data_send
            return self.value_dict
        except Exception:
            del data_send
            return self.value_dict
            # print(traceback.format_exc())

    def load_program(self, fileName):
        fileName = fileName + ".ngc"
        loadDict = '{"cmdName":"load_program","programName":"%s"}' % fileName
        print(loadDict)
        return self.send_get_data(loadDict)

    def run_program(self):
        runDict = '{"cmdName":"play_program"}'
        return self.send_get_data(runDict)

    def query_sysVariable(self):
        queryDict = '{"cmdName":"query_user_defined_variable"}'
        return self.send_get_data(queryDict)

    def modify_sysVariable(self, id, alias, value):
        modifyDict = '{"cmdName":"modify_user_defined_variable","id_new":%d,"alias_new":"%s","value_new":%f}' % (id, alias, value)
        print(modifyDict)
        return self.send_get_data(modifyDict)

    def get_funcdi_status(self):
        funcdiDict = '{"cmdName":"get_funcdi_status"}'
        return self.send_get_data(funcdiDict)

    def get_digital_input_status(self):
        dinDict = '{"cmdName":"get_digital_input_status"}'
        return self.send_get_data(dinDict)

    def get_drag_status(self):
        dragDict = '{"cmdName":"drag_status"}'
        return self.send_get_data(dragDict)

    def get_protective_stop_status(self):
        dict = '{"cmdName":"protective_stop_status"}'
        return self.send_get_data(dict)

    def get_robot_status(self):
        dict = '{"cmdName":"get_robot_state"}'
        return self.send_get_data(dict)

    def get_program_status(self):
        dict = '{"cmdName":"get_program_state"}'
        return self.send_get_data(dict)

    def get_data(self):
        dict = '{"cmdName":"get_data"}'
        return self.send_get_data(dict)

    def set_digital_output(self, type, index, value):
        dict = '{"cmdName":"set_digital_output","type":%d,"index":%d,"value":%d}' % (type, index, value)
        return self.send_get_data(dict)

    def set_analog_output(self, type, index, value):
        dict = '{"cmdName":"set_analog_output","type":%d,"index":%d,"value":%f}' % (type, index, value)
        return self.send_get_data(dict)
